#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

using namespace std;

#define SEP " "             // 分隔符
#define SEP_LEN strlen(SEP) // 分隔符长度，不能用sizeof

#define LINE_SEP "\r\n"

#define LINE_SEP_LINE strlen(LINE_SEP)

enum
{
    OK = 0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR
};

// 协议定制：给报文段加一个特殊字段：有效载荷的长度

//                报头            有效载荷
// 
//"exitcode result"---->"content_len"\r\n"exitcode result"\r\n----
std::string enlength(const std::string &text)
{



    // text就是"x op y"
    string send_string = std::to_string(text.size()); // content_len
    send_string += LINE_SEP;
    send_string += text;
    send_string += LINE_SEP;

    return send_string;
}

// 去掉报头，提取有效载荷
//"content_len"\r\n"exitcode result"\r\n---->exitcode result
bool delength(const std::string &package, std::string *text)
{


    auto pos = package.find(LINE_SEP);
    if (pos == string::npos)
        return false;
    // 提取报头字符串
    string text_len_string = package.substr(0, pos);
    // 将报头信息转化成字符串
    int text_len = std::stoi(text_len_string);
    // 提取有效载荷
    *text = package.substr(pos + LINE_SEP_LINE, text_len);

    return true;
}

// 请求
class Request
{
public:
    Request()
        : x_(0), y_(0), op_(0)
    {
    }
    Request(int x, int y, char op)
        : x_(x), y_(y), op_(op)
    {
    }
    // 序列化
    bool serialize(std::string *out)
    {
#ifdef MYSELF        
        // 将结构化数据转化成-->"x op y"

        out->clear();
        std::string x_string = std::to_string(x_);
        std::string y_string = std::to_string(y_);
        *out = x_string;
        *out += SEP;
        *out += op_;
        *out += SEP;
        *out += y_string;
#else
        Json::Value root;//定义一个万能对象
        root["first"]=x_;
        root["second"]=y_;
        root["oper"]=op_;

        Json::FastWriter writer;
        *out=writer.write(root);

#endif        
        return true;
    }

    // 反序列化
    bool deserialize(const std::string &in)
    {
 #ifdef MYSELF         
        //"x op yyy";
        auto left = in.find(SEP);
        auto right = in.rfind(SEP);

        if (left == std::string::npos || right == std::string::npos)
            return false;
        if (left == right)
            return false;

        // 截取子串
        if (right - (left + SEP_LEN) != 1)
            return false;

        std::string x_string = in.substr(0, left);         // 定位到x
        std::string y_string = in.substr(right + SEP_LEN); // 定位到yyyy

        if (x_string.empty())
            return false;
        if (y_string.empty())
            return false;

        x_ = std::stoi(x_string);
        y_ = std::stoi(y_string);
        op_ = in[left + SEP_LEN]; // 截取op
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in,root);//将解析出来的值放进root里面
        x_=root["first"].asInt();//将val转化成整数
        y_=root["second"].asInt();
        op_=root["oper"].asInt();
#endif
        return true;
    }

public:
    int x_;
    int y_;
    char op_;
};

// 响应
class Response
{
public:
    Response()
        : exitcode_(0), result_(0)
    {
    }
    Response(int exitcode, int result)
        : exitcode_(exitcode), result_(result)
    {
    }

    // 序列化
    bool serialize(std::string *out)
    {
#ifdef MYSELF
        // 清空字符串
        out->clear();
        // 将退出码和结果转换成字符串
        string ec_string = std::to_string(exitcode_);
        string res_string = std::to_string(result_);

        // 合并字符
        *out = ec_string;
        *out += SEP;
        *out += res_string;
#else
        Json::Value root;
        root["exitcode"]=exitcode_;
        root["result"]=result_;
        Json::FastWriter writer;
        *out=writer.write(root);
        

#endif
        return true;
    }

    // 反序列化
    bool deserialize(const std::string &in)
    {

#ifdef MYSELF        
        //"exitcode result"
        auto mid = in.find(SEP);
        if (mid == std::string::npos)
            return false;
        // 截取字符串
        string ec_string = in.substr(0, mid);
        string res_string = in.substr(mid + SEP_LEN);

        if (ec_string.empty() || res_string.empty())
            return false;

        // 写入退出码和结果
        exitcode_ = std::stoi(ec_string);
        result_ = std::stoi(res_string);
#else
        Json::Reader reader;
        Json::Value root;
        reader.parse(in,root);
        exitcode_=root["exitcode"].asInt();
        result_=root["result"].asInt();
#endif
        return true;
    }

public:
    int exitcode_; // 0成功,!0错误
    int result_;   // 计算结果
};

// 读取一个完整的请求放入text里面
//"content_len"\r\n"x op y"\r\n"content_len"\r\n"x op y"\r\n
bool recvRequest(int sock, std::string &inbuffer, string *text)
{
    char buffer[1024];
    while (true)
    {
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            inbuffer += buffer;

            // 边读边处理
            auto pos = inbuffer.find(LINE_SEP);
            // 如果没有读到\r\n，接着去读
            if (pos == string::npos)
                continue;
            // 走到这已经读到了content_len，知道了有效载荷长度

            string text_len_string = inbuffer.substr(0, pos); // 报头
            int text_len = std::stoi(text_len_string);        // 正文长度
            int total_len = text_len_string.size() + 2 * LINE_SEP_LINE + text_len;
            std::cout << "处理前#inbuffer: \n"
                      << inbuffer << endl;
            if (inbuffer.size() < total_len)
            {
                std::cout << "你输入的消息，没有严格遵守我们的协议，正在等待后续的内容, continue" << std::endl;
                continue; // 没有读到一个完整的报文
            }
            // 至少有一个报文
            *text = inbuffer.substr(0, total_len);
            inbuffer.erase(0, total_len);
            std::cout << "处理后#inbuffer: \n"
                      << inbuffer << endl;

            break;
        }
        else
            return false;
    }

    return true;
}